<?php


namespace app\base\service;

use think\admin\service\AdminService;

use think\Cache;
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\Finalseg;
/**
 * 相似度计算服务
 * Class AdminService
 * @package think\admin\service
 */
class SimilarityService extends AdminService
{
    //计算相似度
    public function similarity($text1, $text2) {
        // 示例数据
        $keywords = $this->preprocessText($text1);
        $hotContent = $this->preprocessText($text2);

        // 构建文档集
        $documents = [
            'keywords' => $keywords,
            'content' => $hotContent
        ];

        // 计算TF-IDF
        $tfidf = $this->calculateTFIDF($documents);

        // 获取向量
        $vec1 = $tfidf['keywords'];
        $vec2 = $tfidf['content'];

        // 计算相似度
        return round($this->cosineSimilarity($vec1, $vec2)*100, 2);
    }



    // 文本预处理函数
   protected function preprocessText($text) {
        // 中文需先分词（需安装分词扩展，这里用空格代替）
       ini_set('memory_limit', '512M');
       Jieba::init(['mode' => 'default']);
       Finalseg::init();
       $words = Jieba::cut($text);
       return $words;
    }

    // 计算TF-IDF
    protected  function calculateTFIDF($documents) {
        $tf = [];
        $df = [];
        $totalDocs = count($documents);

        foreach ($documents as $docId => $words) {
            $wordCount = array_count_values($words);
            $totalWords = count($words);

            foreach ($wordCount as $word => $count) {
                $tf[$docId][$word] = $count / $totalWords;
                if (!isset($df[$word])) $df[$word] = 0;
                $df[$word]++;
            }
        }

        $tfidf = [];
        foreach ($tf as $docId => $words) {
            foreach ($words as $word => $tfValue) {
                $idf = log($totalDocs / ($df[$word] + 1));
                $tfidf[$docId][$word] = $tfValue * $idf;
            }
        }

        return $tfidf;
    }

    // 余弦相似度计算
    protected  function cosineSimilarity($vecA, $vecB) {
        $dotProduct = 0;
        $magnitudeA = 0;
        $magnitudeB = 0;

        $allKeys = array_unique(array_merge(array_keys($vecA), array_keys($vecB)));

        foreach ($allKeys as $key) {
            $a = $vecA[$key] ?? 0;
            $b = $vecB[$key] ?? 0;

            $dotProduct += $a * $b;
            $magnitudeA += $a * $a;
            $magnitudeB += $b * $b;
        }

        $magnitude = sqrt($magnitudeA) * sqrt($magnitudeB);
        return $magnitude ? $dotProduct / $magnitude : 0;
    }

}
